package com.dongnao.network.netty;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;

import java.util.concurrent.TimeUnit;

/**
 * 任务队列（TaskQueue）中的Task的3中典型使用场景
 * 1)用户程序自定义的普通任务
 * 2)用户自定义定时任务
 * 3)非当前Reactor 线程调用Channel 的各种方法。如：例如在推送系统的业务线程里面，根据用户的标识，找到对应的Channel引用，然后调用Write类方法向该用户推送消息，就会进入到这种场景。最终的 Write会提交到任务队列中后被异步消费
 */
public class NettyServerHandlerTask extends ChannelInboundHandlerAdapter {

    //读取数据
    /*
    1. ChannelHandlerContext ctx:上下文对象，含有管道pipeline，通道channel，地址
    2. Object msg:就是客户端发送的数据默认 Object
    */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        //比如这里我们有一个非常耗时长的业务->异步执行>提交该channel 对应的NIOEventLoop 的 taskQueue中，

        //解决方案1：用户程序自定义的普通任务
        ctx.channel().eventLoop().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                    ctx.writeAndFlush(Unpooled.copiedBuffer("你好客户端", CharsetUtil.UTF_8));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        //解决方案2：用户自定义定时任务，，该任务提交到scheduledTaskQueue中
        ctx.channel().eventLoop().schedule(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(7000);
                    ctx.writeAndFlush(Unpooled.copiedBuffer("你好客户端2", CharsetUtil.UTF_8));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, 5, TimeUnit.SECONDS);
    }

    //数据读取完毕
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        //writeAndFlush是 write + flush
        //将数据写入缓存并刷新
        //一般要对发送数据进行编码
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello 客户端酱~~~", CharsetUtil.UTF_8));
    }

    //异常处理
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
    }
}
